package cn.hg.solon.youcan.system.provider;

import java.util.List;
import java.util.Map;

import org.dromara.hutool.core.bean.BeanUtil;
import org.dromara.hutool.core.bean.copier.CopyOptions;
import org.dromara.hutool.core.convert.Convert;
import org.dromara.hutool.core.text.CharSequenceUtil;
import org.dromara.hutool.core.text.StrValidator;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.db.PageResult;
import org.noear.solon.annotation.Component;
import org.noear.solon.data.annotation.Tran;

import com.easy.query.api4j.client.EasyQuery;
import com.easy.query.api4j.select.Queryable;
import com.easy.query.core.api.pagination.EasyPageResult;
import com.easy.query.solon.annotation.Db;

import cn.hg.solon.youcan.common.constant.AppConstants;
import cn.hg.solon.youcan.common.constant.WebConstants;
import cn.hg.solon.youcan.common.exception.ServiceException;
import cn.hg.solon.youcan.system.entity.Config;
import cn.hg.solon.youcan.system.entity.EqConfig;
import cn.hg.solon.youcan.system.service.ConfigService;

/**
 * @author 胡高
 */
@Component
public class EqConfigProvider implements ConfigService {

    @Db("db1")
    private EasyQuery easyQuery;

    private Queryable<EqConfig> buildQuery(Map<String, Object> paraMap) {
        String type = (String)paraMap.get("type");
        String word = (String)paraMap.get("word");
        String sortField = (String)paraMap.get("sortField");
        String sortType = (String)paraMap.get("sortType");

        boolean customOrder = StrValidator.isNotBlank(sortField) && StrValidator.isNotBlank(sortType);

        // FROM sys_config AS t
        return this.easyQuery.queryable(EqConfig.class)
            // WHERE t.`type` = ${type} AND (t.`name` LIKE '%${word}%' OR t.`code` LIKE '%${word}%'
            //      OR t.`value` LIKE '%${word}%')
            .where(w -> w.eq(StrValidator.isNotBlank(type), EqConfig::getType, type)
                .and(StrValidator.isNotBlank(word),
                    a -> a.like(EqConfig::getName, word)
                    .or().like(EqConfig::getCode, word)
                    .or().like(EqConfig::getValue, word)))
            // ORDER BY ${sortField} DESC
            .orderBy(customOrder, ob -> ob.sqlNativeSegment(CharSequenceUtil.toUnderlineCase(sortField)),
                !CharSequenceUtil.equalsIgnoreCase(sortType, WebConstants.ORDER_DIRECTION_DESC));
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.ConfigService#checkUnique(cn.hg.solon.youcan.system.entity.Config)
     */
    @Override
    public boolean checkUnique(Config bean) {
        // FROM sys_role AS t
        return !this.easyQuery.queryable(EqConfig.class)
            // WHERE t.`type` = ${bean.type} AND t.`code` = ${bean.code} AND t.`id` <> ${bean.id}
            .where(w -> w.eq(EqConfig::getType, bean.getType())
                .eq(EqConfig::getCode, bean.getCode())
                .ne(ObjUtil.isNotNull(bean.getId()), EqConfig::getId, bean.getId())).any();
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.ConfigService#delete(java.util.List)
     */
    @Tran
    @Override
    public boolean delete(List<Integer> idList) {
        for (Integer id : idList) {
            Config item = this.get(id);

            if (ObjUtil.isNotNull(item) && item.getIsSys()) {
                throw new ServiceException(AppConstants.RETURN_CODE_VALUE_FAILED,
                    "[" + item.getName() + "] 为系统参数，不允许删除！");
            }
        }

        return this.easyQuery.deletable(EqConfig.class).where(w -> w.in(EqConfig::getId, idList)).executeRows() > 0;
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.ConfigService#get(java.lang.Integer)
     */
    @Override
    public Config get(Integer id) {
        return this.easyQuery.queryable(EqConfig.class).whereById(id).firstOrNull();
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.ConfigService#getByTypeAndCode(java.lang.String, java.lang.String)
     */
    @Override
    public Config getByTypeAndCode(String type, String code) {
        EqConfig bean = this.easyQuery.queryable(EqConfig.class)
            .where(w -> w.eq(EqConfig::getType, type).eq(EqConfig::getCode, code)).firstOrNull();
        return bean;
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.ConfigService#insert(cn.hg.solon.youcan.system.entity.Config)
     */
    @Tran
    @Override
    public boolean insert(Config bean) {
        if (!this.checkUnique(bean)) {
            throw new ServiceException(AppConstants.RETURN_CODE_VALUE_FAILED, "参数代码已经存在，请更换其它值！");
        }

        EqConfig cloneBean = BeanUtil.copyProperties(bean, EqConfig.class);

        return this.easyQuery.insertable(cloneBean).executeRows() > 0;
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.ConfigService#listByType(java.lang.String)
     */
    @Override
    public List<? extends Config> listByType(String type) {
        return this.easyQuery.queryable(EqConfig.class).where(w -> w.eq(EqConfig::getType, type)).toList();
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.ConfigService#pageBy(int, int, java.util.Map)
     */
    @Override
    public PageResult<EqConfig> pageBy(int pageNumber, int pageSize, Map<String, Object> paraMap) {
        EasyPageResult<EqConfig> pageList = this.buildQuery(paraMap).toPageResult(Convert.toLong(pageNumber), pageSize);

        PageResult<EqConfig> result = new PageResult<>();
        result.addAll(pageList.getData());
        result.setTotal(Convert.toInt(pageList.getTotal()));

        return result;
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.ConfigService#update(cn.hg.solon.youcan.system.entity.Config)
     */
    @Tran
    @Override
    public boolean update(Config bean) {
        if (!this.checkUnique(bean)) {
            throw new ServiceException(AppConstants.RETURN_CODE_VALUE_FAILED, "参数代码已经存在，请更换其它值！");
        }

        EqConfig cloneBean = (EqConfig)this.get(bean.getId());

        BeanUtil.copyProperties(bean, cloneBean, CopyOptions.of().setIgnoreNullValue(true));

        return this.easyQuery.updatable(cloneBean).executeRows() > 0;
    }

}
